﻿#include "onemap.h"
#define D_START_ID 500
OneMap::OneMap():
    max_id(D_START_ID)
{

}

OneMap::~OneMap()
{
    for(auto f:all_element)delete f;
}

int OneMap::getSplineStartAngle(int pathId, double &angleOut)
{
    MapPath *tmpPath=getPathById(pathId);
    MapPoint *tmpStart=getPointById(tmpPath->getStart());
    MapPoint *tmpEnd=getPointById(tmpPath->getEnd());
    if(MapPath::Map_Path_Type_Cubic_Bezier!=tmpPath->getPathType())
    {
        double tmpLineAngle=atan2(tmpEnd->getY()-tmpStart->getY(),tmpEnd->getX()-tmpStart->getX());
        angleOut=180.0*tmpLineAngle/M_PI;
        return 1;
    }
    double tmpLineAngle=atan2(tmpPath->getP1y()-tmpStart->getY(),tmpPath->getP1x()-tmpStart->getX());
    angleOut=180.0*tmpLineAngle/M_PI;
    return 1;
}

int OneMap::getSplineEndAngle(int pathId, double &angleOut)
{
    MapPath *tmpPath=getPathById(pathId);
    MapPoint *tmpStart=getPointById(tmpPath->getStart());
    MapPoint *tmpEnd=getPointById(tmpPath->getEnd());
    if(MapPath::Map_Path_Type_Cubic_Bezier!=tmpPath->getPathType())
    {
        double tmpLineAngle=atan2(-tmpStart->getY()+tmpEnd->getY(),-tmpStart->getX()+tmpEnd->getX());
        angleOut=180.0*tmpLineAngle/M_PI;
        return 1;
    }
    double tmpLineAngle=atan2(-tmpPath->getP2y()+tmpEnd->getY(),-tmpPath->getP2x()+tmpEnd->getX());
    angleOut=180.0*tmpLineAngle/M_PI;
    return 1;
}

int OneMap::setDisplayRatio(double ratioIn)
{
    displayRatio=ratioIn;
    return 1;
}

double OneMap::getDisplayRatio()
{
    return displayRatio;
}


int OneMap::modifyFloorId(int oldId, int newId)
{
    MapFloor * tmpFloor=getFloorById(oldId);
    if(nullptr==tmpFloor)
    {
        return 0;
    }
    std::list<MapSpirit *> tmpIdList= getAllElement();
    for (auto p : tmpIdList)
    {

        if(newId==p->getId())
        {
            return -1;
        }
    }
    tmpFloor->setId(newId);
    if(newId>getMaxId())
    {
        setMaxId(newId);
    }

    return 1;
}

int OneMap::modifyBackgroundId(int oldId, int newId)
{
    MapBackground * tmpFloor=getBackgroundById(oldId);
    if(nullptr==tmpFloor)
    {
        return 0;
    }
    std::list<MapSpirit *> tmpIdList= getAllElement();
    for (auto p : tmpIdList)
    {

        if(newId==p->getId())
        {
            return -1;
        }
    }
    tmpFloor->setId(newId);
    if(newId>getMaxId())
    {
        setMaxId(newId);
    }
    //修改floor包含关系
    std::list<MapFloor *> tmpFloorList= getFloors();
    for (auto p : tmpFloorList)
    {
        p->changeBkgId(oldId,newId);
    }


    return 1;
}

int OneMap::modifyPathId(int oldId, int newId)
{
    MapPath * tmpFloor=getPathById(oldId);
    if(nullptr==tmpFloor)
    {
        return 0;
    }
    std::list<MapSpirit *> tmpIdList= getAllElement();
    for (auto p : tmpIdList)
    {

        if(newId==p->getId())
        {
            return -1;
        }
    }
    tmpFloor->setId(newId);
    if(newId>getMaxId())
    {
        setMaxId(newId);
    }

    //修改floor包含关系
    std::list<MapFloor *> tmpFloorList= getFloors();
    for (auto p : tmpFloorList)
    {
        p->changePathId(oldId,newId);
    }

    return 1;
}

int OneMap::modifyPointId(int oldId, int newId,std::string newNameIn)
{
    if(nullptr==getPointById(oldId))
    {
        qDebug()<<"failed,,,nullptr==getPointById(oldId)";
        return -1;
    }
    std::list<MapSpirit *> tmpIdList= getAllElement();
    for (auto p : tmpIdList)
    {

        if(newId==p->getId())
        {
            switch(p->getSpiritType())
            {
            case MapSpirit::Map_Sprite_Type_Point://如果station 占用了id
            {
                qDebug()<<"failed,,,station 占用了id";
                return -2;
                break;
            }
            case MapSpirit::Map_Sprite_Type_Path:
            {
                modifyPathId(newId,getNextId());
                break;
            }
            case MapSpirit::Map_Sprite_Type_Floor:
            {
                modifyFloorId(newId,getNextId());
                break;
            }
            case MapSpirit::Map_Sprite_Type_Background:
            {
                modifyBackgroundId(newId,getNextId());
                break;
            }
            case MapSpirit::Map_Sprite_Type_Block:
            {
                qDebug()<<"failed,,,Map_Sprite_Type_Block";
                return -3;
                break;
            }
            case MapSpirit::Map_Sprite_Type_Group:
            {
                qDebug()<<"failed,,,Map_Sprite_Type_Group";
                return -4;
                break;
            }

            }


        }
    }


    //修改id
    MapPoint  *tmpPoint =getPointById(oldId);
    tmpPoint->setId(newId);
    tmpPoint->setName(newNameIn);
    if(newId>getMaxId())
    {
        setMaxId(newId);
    }

    //更新line连接关系
    std::list<MapPath *>tmpPathList= getPaths();
    for (auto p : tmpPathList)
    {
        bool isLineChanged=false;
        if(p->getStart()==oldId)
        {
            p->setStart(newId);
            isLineChanged=true;
        }
        if(p->getEnd()==oldId)
        {
            p->setEnd(newId);
            isLineChanged=true;
        }
        //修改path name
        if(isLineChanged)
        {
            std::string  tmpPathName;
            MapPoint  *tmpStartPoint =getPointById(p->getStart());
            MapPoint  *tmpEndPoint =getPointById(p->getEnd());
            tmpPathName=tmpStartPoint->getName();
            tmpPathName+="-";
            tmpPathName+=tmpEndPoint->getName();
            p->setName(tmpPathName);
        }
    }



    //修改line包含关系
    std::list<MapFloor *> tmpFloorList= getFloors();
    for (auto p : tmpFloorList)
    {
        p->changePointId(oldId,newId);
    }
    return 1;
}


void OneMap::setVersion(int versionIn)
{
    version=versionIn;
}

int OneMap::getVersion()
{
    return version;
}

void OneMap::clear()
{
    for(auto f:all_element)delete f;
    all_element.clear();
    max_id = D_START_ID;
    version=0;
}

void OneMap::addSpirit(MapSpirit *spirit)
{
    all_element.push_back(spirit);
}

void OneMap::removeSpirit(MapSpirit *spirit)
{
    all_element.remove(spirit);
}

void OneMap::removeSpiritById(int id)
{
    for(auto itr = all_element.begin();itr!=all_element.end();){
        if((*itr)->getId() == id){
            itr = all_element.erase(itr);
        }else{
            itr++;
        }
    }
}

int OneMap::getNextId()
{
    return ++max_id;
}

//复制整个地图
OneMap *OneMap::clone()
{
    OneMap *onemap = new OneMap;
    onemap->setMaxId(max_id);
    for (auto e : all_element) {
        onemap->addSpirit(e->clone());
    }
    onemap->setDisplayRatio(displayRatio);
    onemap->setVersion(version);
    return onemap;
}

std::list<MapPoint *> OneMap::getPoints_sort()
{
    std::list<MapPoint *> tmpList=getPoints();
    std::list<int> pointIds;
    for (auto p : tmpList)
    {
        pointIds.push_back(p->getId());
    }
    pointIds.sort();
    tmpList.clear();
    for (auto p : pointIds)
    {
        tmpList.push_back(getPointById(p));
    }
    return tmpList;

}

std::list<MapPoint *> OneMap::getPoints()
{
    std::list<MapPoint *> tmpList;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Point)tmpList.push_back((MapPoint *)s);
    }
    return tmpList;
}

MapSpirit *OneMap::getSpiritById(int id)
{
    for (auto p : all_element) {
        if(p->getId() == id)return p;
    }
    return nullptr;
}

MapPoint *OneMap::getPointById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Point) {
            return static_cast<MapPoint *>(p);
        }
    }
    return nullptr;
}
MapPath *OneMap::getPathById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Path) {
            return static_cast<MapPath *>(p);
        }
    }
    return nullptr;
}
MapPath *OneMap::getPathByStartEnd(int start,int end)
{
    for (auto p : all_element) {
        if (p->getSpiritType() == MapSpirit::Map_Sprite_Type_Path) {
            auto pp = static_cast<MapPath *>(p);
            if(pp->getStart() == start && pp->getEnd() == end){
                return pp;
            }
        }
    }
    return nullptr;
}

MapFloor *OneMap::getFloorById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Floor) {
            return static_cast<MapFloor *>(p);
        }
    }
    return nullptr;
}
MapBackground *OneMap::getBackgroundById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Background) {
            return static_cast<MapBackground *>(p);
        }
    }
    return nullptr;
}
MapBlock *OneMap::getBlockById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Block) {
            return static_cast<MapBlock *>(p);
        }
    }
    return nullptr;
}
MapGroup *OneMap::getGroupById(int id)
{
    for (auto p : all_element) {
        if (p->getId() == id && p->getSpiritType() == MapSpirit::Map_Sprite_Type_Group) {
            return static_cast<MapGroup *>(p);
        }
    }
    return nullptr;
}


std::vector<int> OneMap::getStations()
{
    std::vector<int> points;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Point)points.push_back(s->getId());
    }
    return points;
}

std::list<MapFloor *> OneMap::getFloors()
{
    std::list<MapFloor *> floors;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Floor)floors.push_back(static_cast<MapFloor *>(s));
    }
    return floors;
}

std::list<MapPath *> OneMap::getPaths()
{
    std::list<MapPath *> paths;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Path)paths.push_back(static_cast<MapPath *>(s));
    }
    return paths;
}

std::list<MapPath *> OneMap::getPaths_sort()
{
    std::list<MapPath *> tmpList=getPaths();
    std::list<int> pointIds;
    for (auto p : tmpList)
    {
        pointIds.push_back(p->getId());
    }
    pointIds.sort();
    tmpList.clear();
    for (auto p : pointIds)
    {
        tmpList.push_back(getPathById(p));
    }
    return tmpList;
}

std::list<MapPath *> OneMap::getRootPaths()
{
    std::list<MapPath *> all_paths = getPaths();
    std::list<MapFloor *> floors = getFloors();//楼层
    for(auto itr=all_paths.begin();itr!=all_paths.end();){
        //是否楼层上的路径
        bool isFloorPath = false;
        for(auto f:floors){
            if(isFloorPath)break;
            std::list<int> fps = f->getPaths();
            for(auto fp:fps){
                if((*itr)->getId() == fp){
                    isFloorPath = true;
                    break;
                }
            }
        }
        if(isFloorPath){
            itr = all_paths.erase(itr);
        }else{
            itr++;
        }
    }
    return all_paths;
}

std::list<MapBlock *> OneMap::getBlocks()
{
    std::list<MapBlock *> blocks;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Block)
        {
            blocks.push_back(static_cast<MapBlock *>(s));
        }
    }
    return blocks;
}

std::list<MapGroup *> OneMap::getGroups()
{
    std::list<MapGroup *> groups;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Group)
        {
            groups.push_back(static_cast<MapGroup *>(s));
        }
    }
    return groups;
}

std::list<MapGroup *> OneMap::getGroups(int groupType)
{
    std::list<MapGroup *> groups;
    for(auto s:all_element)
    {
        if(s->getSpiritType() == MapSpirit::Map_Sprite_Type_Group)
        {
            MapGroup* group = static_cast<MapGroup *>(s);
            if(group->getGroupType() == groupType)
                groups.push_back(group);
        }
    }
    return groups;
}

